package com.arsProfundis.dal.mongo
	
import com.mongodb.DBObject
import com.mongodb.casbah.Imports._

import com.arsProfundis.dal.contracts._



abstract class MongoAbstractDao[T, ID <: AnyRef] extends AbstractDao[T, ID]{

/* TODO MongoCollection instantiation move to Guice*/
	val mongoConnection = MongoConnection("mongodb", 42017)
	val mongoCollection = mongoConnection("casbah_test")("test_data")

	implicit protected val dbObject2DomainObjectMapper: DBObject => Either[Exception, T]
	implicit protected val domainObject2DbObjectMapper: T => DBObject


	def insert(entity: T) : Either[Exception, String] = {
		try{
			val dbObject: DBObject = domainObject2DbObjectMapper(entity)
			val result: WriteResult = mongoCollection.insert(dbObject)
			Right(dbObject.getAs[String]("_id").get)
		}
		catch{
			case ex: Exception => Left(ex)
		}
	}

	def save(entity: T): Option[Exception] = {
		try{
			val result = mongoCollection.save[T](entity)
			None
		}
		catch{
			case ex: Exception => Some(new Exception(ex))
		}
	}

	def delete(id: ID): Option[Exception] = {
		try{
			mongoCollection.remove(MongoDBObject("_id" -> id))
			None
		}
		catch{
			case ex: Exception => Some(new Exception(ex))
		}
	}

	def getById(id: ID): Either[Exception, Option[T]] ={
		try{
			mongoCollection.findOneByID(id) match{
			case None => Right(None)
			case Some(dbObject) => dbObject2DomainObjectMapper.apply(dbObject).right.map(Option(_))
			}
		}
		catch {
			case ex: Exception => Left(ex)
		}
	}
}